package org.droidplanner.android.fragments.widget.video

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.SurfaceTexture
import android.hardware.usb.UsbDevice
import android.os.Bundle
import android.util.Log
import android.view.*
import android.widget.TextView
import com.o3dr.services.android.lib.drone.attribute.AttributeEvent
import com.o3dr.services.android.lib.drone.attribute.AttributeType
import com.o3dr.services.android.lib.drone.property.State
import com.serenegiant.usb.DeviceFilter
import com.serenegiant.usb.USBMonitor
import com.serenegiant.usb.UVCCamera
import org.droidplanner.android.R
import org.droidplanner.android.dialogs.UVCDialog
import org.droidplanner.android.fragments.widget.TowerWidget
import org.droidplanner.android.fragments.widget.TowerWidgets
import java.util.concurrent.LinkedBlockingQueue
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
import android.graphics.Matrix
import com.skydroid.fpvplayer.FPVReaderWidget
import com.skydroid.fpvplayer.ffmpeg.FFmpegStreamClient
import com.skydroid.rcsdk.PipelineManager
import com.skydroid.rcsdk.comm.CommListener
import com.skydroid.rcsdk.common.error.SkyException
import com.skydroid.rcsdk.common.pipeline.Pipeline
import org.droidplanner.android.utils.prefs.DroidPlannerPrefs
import java.util.*

abstract class BaseUVCVideoWidget : TowerWidget(){

    companion object {

        private val filter = initFilter()

        private fun initFilter(): IntentFilter {
            val temp = IntentFilter()
            temp.addAction(AttributeEvent.STATE_CONNECTED)
            return temp
        }

    }

    protected val DEBUG = false

    protected val TAG = "BaseUVCVideoWidget"

    override fun getWidgetType() = TowerWidgets.UVC_VIDEO

    //Aspect ratio
    protected val ASPECT_RATIO_4_3: Float = 3f / 4f
    protected val ASPECT_RATIO_16_9: Float = 9f / 16f
    protected val ASPECT_RATIO_21_9: Float = 9f / 21f
    protected val ASPECT_RATIO_1_1: Float = 1f / 1f
    protected var aspectRatio: Float = ASPECT_RATIO_4_3

    protected var mUSBMonitor: Pipeline? = null
    protected var isPreview:Boolean = false

    protected val receiver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            when (intent.action) {
                AttributeEvent.STATE_CONNECTED -> {
//                    startVideoStreaming()
                }
            }
        }
    }

    protected val textureView by lazy(LazyThreadSafetyMode.NONE) {
        view?.findViewById(R.id.uvc_video_view) as H264FPVReaderWidget?
    }

    protected val videoStatus by lazy(LazyThreadSafetyMode.NONE) {
        view?.findViewById(R.id.uvc_video_status) as TextView?
    }

    override fun onApiConnected() {
        if (DEBUG) Log.v(TAG, "onApiConnected:")

        broadcastManager.registerReceiver(receiver, filter)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?){
        super.onViewCreated(view, savedInstanceState)
        //H12 Camear
        textureView?.start(640,360,15)
        //H12 Video SerialPort
        mUSBMonitor = PipelineManager.createSerialPipeline("/dev/ttyHS0",4000000)
        mUSBMonitor?.onCommListener = object : CommListener{
            override fun onConnectSuccess() {
                view?.post {
                    videoStatus?.visibility = View.GONE
                }
            }

            override fun onConnectFail(p0: SkyException?) {

            }

            override fun onDisconnect() {
                view?.post { videoStatus?.visibility = View.VISIBLE }
            }

            override fun onReadData(p0: ByteArray?) {
                p0 ?: return
                val a = ByteArray(p0.size)
                System.arraycopy(p0,0,a,0,p0.size)
                textureView?.sendFrame(a)
            }
        }
        if (DEBUG) Log.v(TAG, "onViewCreated:")

    }

    override fun onResume() {
        super.onResume()
        if (DEBUG) Log.v(TAG, "onResume:")

        mUSBMonitor?.let {
            PipelineManager.connectPipeline(it)
        }

        aspectRatio = appPrefs.uvcVideoAspectRatio
    }

    override fun onPause() {
        super.onPause()
        if (DEBUG) Log.v(TAG, "onPause:")

        mUSBMonitor?.let {
            PipelineManager.disconnectPipeline(it)
        }
        appPrefs.uvcVideoAspectRatio = aspectRatio
    }

    override fun onDestroy() {
        super.onDestroy()
        textureView?.stop()
        if (DEBUG) Log.v(TAG, "onDestroy:")
        isPreview = false
        mUSBMonitor = null
    }

    override fun onApiDisconnected() {
        broadcastManager.unregisterReceiver(receiver)
        if (DEBUG) Log.v(TAG, "onApiDisconnected:")
    }

    protected fun adjustAspectRatio(textureView: H264FPVReaderWidget) {
        val viewWidth = textureView.width
        val viewHeight = textureView.height

        val newWidth: Int
        val newHeight: Int
        if (viewHeight > (viewWidth * aspectRatio)) {
            //limited by narrow width; restrict height
            newWidth = viewWidth
            newHeight = (viewWidth * aspectRatio).toInt()
        } else {
            //limited by short height; restrict width
            newWidth = (viewHeight / aspectRatio).toInt();
            newHeight = viewHeight
        }

        val xoff = (viewWidth - newWidth) / 2f
        val yoff = (viewHeight - newHeight) / 2f

        val txform = Matrix();
        textureView.getTransform(txform);
        txform.setScale((newWidth.toFloat() / viewWidth), newHeight.toFloat() / viewHeight);

        txform.postTranslate(xoff, yoff);
        textureView.setTransform(txform);
    }



}